home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_asm / nnansi3 / nnansi_p.asm < prev    next >
Assembly Source File  |  1989-09-25  |  10KB  |  320 lines

  1.     page    66, 132
  2. ;----- nnansi_p.asm --------------------------------------------------------
  3. ; A state machine implementation of the mechanics of ANSI terminal control
  4. ; string parsing.
  5. ; (C) 1986 Daniel Kegel, Pasadena, CA
  6. ; May be distributed for educational and personal use only
  7. ;
  8. ; Entered with a jump to f_escape when driver finds an escape, or
  9. ; to f_in_escape when the last string written to this device ended in the
  10. ; middle of an escape sequence.
  11. ;
  12. ; Exits by jumping to f_ANSI_exit when an escape sequence ends, or
  13. ; to f_not_ANSI when a bad escape sequence is found, or (after saving state)
  14. ; to f_loopdone when the write ends in the middle of an escape sequence.
  15. ;
  16. ; Parameters are stored as bytes in param_buffer.  If a parameter is
  17. ; omitted, it is stored as zero.  Each character in a keyboard reassignment
  18. ; command counts as one parameter.
  19. ;
  20. ; When a complete escape sequence has been parsed, the address of the
  21. ; ANSI routine to call is found in ansi_fn_table.
  22. ;
  23. ; Register usage during parsing:
  24. ;  DS:SI points to the incoming string.
  25. ;  CX holds the length remaining in the incoming string.
  26. ;  ES:DI points to the current location on the memory-mapped screen.
  27. ;  DX is number of characters remaining on the current screen line.
  28. ;  BX points to the current paramter byte being assembled from the incoming
  29. ;  string.  (Stored in cur_parm_ptr between device driver calls, if needed.)
  30. ;
  31. ; The registers are set as follows before calling the ANSI subroutine:
  32. ;  AX = max(1, value of first parameter)
  33. ;  CX = number of paramters
  34. ;  SI = offset of second parameter from CS
  35. ;  DS = CS
  36. ;  ES:DI points to the current location on the memory-mapped screen.
  37. ;  DX is number of characters remaining on the current screen line.
  38. ; The subroutine is free to trash AX, BX, CX, SI, and DS.
  39. ; It must preserve ES, and can alter DX and DI if it wants to move the
  40. ; cursor.
  41. ;
  42. ; Revision history:
  43. ; 7 July 85: created by DRK
  44. ; 8 Jan  89: Slight mods for options by TAA
  45. ;------------------------------------------------------------------------
  46.  
  47.     include nnansi_d.asm
  48.  
  49.     ; From nnansi.asm
  50.     extrn    f_not_ANSI:near        ; exit: abort bad ANSI cmd
  51.     extrn    f_ANSI_exit:near    ; exit: good cmd done
  52.     extrn    f_loopdone:near        ; exit: ran out of chars. State saved.
  53.     extrn    escvector:word        ; saved state: where to jump
  54.     extrn    cur_parm_ptr:word    ; saved state: where to put next param
  55.     extrn    string_term:byte    ; saved state: what ends string
  56.     extrn    cur_x:byte, max_x:byte    ; 0 <= cur_x <= max_x
  57.     extrn    cur_attrib:byte        ; current color/attribute
  58. if out_trans
  59.     extrn    xlate_tab_ptr:word
  60. endif
  61.     ; from nnansi_f.asm
  62.     extrn    ansi_fn_table:word    ; ANSI subroutine table
  63.  
  64.     ; Used in nnansi.asm
  65.     public    f_escape        ; entry: found an escape
  66.     public    f_in_escape        ; entry: restore state, keep parsing
  67.  
  68.     ; Used in nnansi_i.asm and nnansi_f.asm
  69.     public    param_buffer, param_end
  70. if key_redef
  71.     public    redef_end
  72. endif
  73.  
  74. code    segment byte public 'CODE'
  75.     assume    cs:code
  76.  
  77. ; More saved state
  78. in_num        db    ?    ; true if between a digit and a semi in parse
  79.  
  80. param_buffer    dw    3000h    ; address of first byte free for new params
  81. param_end    dw    3030h    ; address of end of free area
  82. if key_redef
  83. redef_end    dw    3030h    ; address of end of redefinition area
  84. endif
  85.         ; These initialized values are only for debugging
  86.  
  87. ;----- next_is -------------------------------------------------------
  88. ; Next_is is used to advance to the next state.     If there are characters
  89. ; left in the input string, we jump immediately to the new state;
  90. ; otherwise, we shut down the recognizer, and wait for the next call
  91. ; to the device driver.
  92. next_is macro    statename
  93.     loop    statename
  94.     mov    ax, offset statename
  95.     jmp    sleep
  96.     endm
  97.  
  98. ;----- sleep --------------------------------------------------------
  99. ; Remember bx and next state, then jump to device driver exit routine.
  100. ; Device driver will re-enter at f_in_escape upon next invocation
  101. ; because escvector is nonzero; parsing will then be resumed.
  102. sleep:    mov    cs:cur_parm_ptr, bx
  103.     mov    cs:escvector, ax
  104.     jmp    f_loopdone
  105.  
  106. ;----- f_in_escape ---------------------------------------------------
  107. ; Main loop noticed that escvector was not zero.
  108. ; Recall value of BX saved when sleep was jumped to, and jump into parser.
  109. f_in_escape:
  110.     mov    bx, cs:cur_parm_ptr
  111.     jmp    word ptr cs:escvector
  112.  
  113. fbr_syntax_error_gate:        ; jumped to from inside f_bracket
  114.     jmp    syntax_error
  115.  
  116. ;----- f_escape ------------------------------------------------------
  117. ; We found an escape.  Next character should be a left bracket.
  118. f_escape:
  119.     next_is f_bracket
  120.  
  121. ;----- f_bracket -----------------------------------------------------
  122. ; Last char was an escape.  This one should be a [; if not, print it.
  123. ; Next char should begin a parameter string.
  124. f_bracket:
  125.     lodsb
  126.     cmp    al, '['
  127.     jnz    fbr_syntax_error_gate
  128.     ; Set up for getting a parameter string.
  129.     mov    bx, cs:param_buffer
  130.     mov    byte ptr cs:[bx], 0
  131.     mov    cs:in_num, 0
  132.     next_is f_get_args
  133.  
  134. ;----- f_get_args ---------------------------------------------------
  135. ; Last char was a [.  If the current char is a '=' or a '?', eat it.
  136. ; In any case, proceed to f_get_param.
  137. ; This is only here to strip off the strange chars that follow [ in
  138. ; the SET/RESET MODE escape sequence.
  139. f_get_args:
  140.     lodsb
  141.     cmp    al, '='
  142.     jz    fga_ignore
  143.     cmp    al, '?'
  144.     jz    fga_ignore
  145.         dec    si        ; let f_get_param fetch al again
  146.         jmp    short f_get_param
  147. fga_ignore:
  148.     next_is f_get_param
  149.  
  150. ;----- f_get_param ---------------------------------------------------
  151. ; Last char was one of the four characters "]?=;".
  152. ; We are getting the first digit of a parameter, a quoted string,
  153. ; a ;, or a command.
  154. f_get_param:
  155.     lodsb
  156.     cmp    al, '0'
  157.     jb    fgp_may_quote
  158.     cmp    al, '9'
  159.     ja    fgp_may_quote
  160.         ; It's the first digit.     Initialize current parameter with it.
  161.         sub    al, '0'
  162.         mov    byte ptr cs:[bx], al
  163.         mov    cs:in_num, 1    ; set flag for sensing at cmd exec
  164.         next_is f_in_param
  165. fgp_may_quote:
  166.     cmp    al, '"'
  167.     jz    fgp_isquote
  168.     cmp    al, "'"
  169.     jnz    fgp_semi_or_cmd        ; jump to code shared with f_in_param
  170. fgp_isquote:
  171.     mov    cs:string_term, al    ; save it for end of string
  172.     next_is f_get_string        ; and read string into param_buffer
  173.  
  174. ;----- f_get_string -------------------------------------
  175. ; Last character was a quote or a string element.
  176. ; Get characters until ending quote found.
  177. f_get_string:
  178.     lodsb
  179.     cmp    al, cs:string_term
  180.     jz    fgs_init_next_param
  181.     mov    byte ptr cs:[bx], al
  182.     cmp    bx, cs:param_end
  183.     adc    bx, 0            ; if bx<param_end bx++;
  184.     next_is f_get_string
  185. ; Ending quote was found.
  186. fgs_init_next_param:
  187.     mov    byte ptr cs:[bx], 0    ; initialize new parameter
  188.     ; | Eat following semicolon, if any.
  189.     next_is f_eat_semi
  190.  
  191. ;----- f_eat_semi -------------------------------------
  192. ; Last character was an ending quote.
  193. ; If this char is a semi, eat it; else unget it.
  194. ; Next state is always f_get_param.
  195. f_eat_semi:
  196.     lodsb
  197.     cmp    al, ';'
  198.     jz    fes_eaten
  199.         inc    cx
  200.         dec    si
  201. fes_eaten:
  202.     next_is f_get_param
  203.  
  204. ;----- syntax_error ---------------------------------------
  205. ; A character was rejected by the state machine.  Exit to
  206. ; main loop, and print offending character.  Let main loop
  207. ; decrement CX (length of input string).
  208. syntax_error:
  209.     mov    cs:escvector, 0
  210.     mov    ah, cs:cur_attrib
  211. if out_trans
  212.     mov    bx, cs:xlate_tab_ptr
  213. endif
  214.     jmp    f_not_ANSI    ; exit, print offending char
  215.  
  216. ;------ f_in_param -------------------------------------
  217. ; Last character was a digit.
  218. ; Looking for more digits, a semicolon, or a command character.
  219. f_in_param:
  220.     lodsb
  221.     cmp    al, '0'
  222.     jb    fgp_semi_or_cmd
  223.     cmp    al, '9'
  224.     ja    fgp_semi_or_cmd
  225.         ; It's another digit.  Add into current parameter.
  226.         sub    al, '0'
  227.         xchg    byte ptr cs:[bx], al
  228.         push    dx
  229.         mov    dl, 10
  230.         mul    dl
  231.         pop    dx
  232.         add    byte ptr cs:[bx], al
  233.         next_is f_in_param
  234.     ; Code common to states get_param and in_param.
  235.     ; Accepts a semicolon or a command letter.
  236. fgp_semi_or_cmd:
  237.     cmp    al, ';'
  238.     jnz    fgp_not_semi
  239.         cmp    bx, cs:param_end    ; prepare for next param-
  240.         adc    bx, 0            ; if bp<param_end bp++;
  241.         ; Set new param to zero, enter state f_get_param.
  242.         mov    cs:in_num, 0        ; no longer inside number
  243.         jmp    fgs_init_next_param    ; spaghetti code attack!
  244. fgp_not_semi:
  245.     ; It must be a command letter.
  246.     cmp    al, '@'
  247.     jb    syntax_error
  248.     cmp    al, 'z'
  249.     ja    syntax_error
  250.     cmp    al, 'Z'
  251.     jbe    fgp_is_cmd
  252.     cmp    al, 'a'
  253.     jb    syntax_error
  254.         ; It's a lower-case command letter.
  255.         ; Remove hole between Z and a to save space in table.
  256.         sub    al, 'a'-'['
  257. fgp_is_cmd:
  258.     ; It's a command letter.  Save registers, convert letter
  259.     ; into address of routine, set up new register usage, call routine.
  260.     push    si            ; These three registers hold info
  261.     push    cx            ; having to do with the input string,
  262.     push    ds            ; which has no interest at all to the
  263.                     ; control routine.
  264.  
  265.     push    cs
  266.     pop    ds            ; ds is now cs
  267.  
  268.     sub    al, '@'            ; first command is @: insert chars
  269.     cbw
  270.     add    ax, ax
  271.     add    ax, offset ansi_fn_table
  272.     ; ax is now pointer to command routine address in table
  273.  
  274.     mov    cx, bx
  275.     mov    si, param_buffer    ; si is now pointer to parameters
  276.     sub    cx, si            ;
  277.     test    in_num, 1
  278.     jz    fip_out_num
  279.         inc    cx
  280. fip_out_num:                ; cx is now # of parameters
  281.  
  282.     xchg    ax, bx            ; save pointer to routine in bx
  283.  
  284.     ; Calculate cur_x from DX.
  285.     mov    al, max_x
  286.     inc    ax
  287.     sub    al, dl
  288.     mov    cur_x, al
  289.  
  290.     ; Get first parameter into AX; if defaulted, set it to 1.
  291.     mov    ah, 0
  292.     lodsb
  293.     or    al, al
  294.     jnz    fgp_callem
  295.         pushf        ; save zero flag (TAA fix)
  296.         inc    ax
  297.         popf
  298. fgp_callem:
  299.     ; Finally, call the command subroutine.
  300.     call    word ptr [bx]
  301.  
  302.     pop    ds
  303.     pop    cx
  304.     pop    si
  305.  
  306.     mov    ah, cs:cur_attrib    ; Prepare for STOSW.
  307. if out_trans
  308.     mov    bx, cs:xlate_tab_ptr    ; Prepare for translation.
  309. endif
  310.     mov    cs:escvector, 0        ; No longer parsing escape sequence.
  311.     ; Set flags for reentry at loopnz
  312.     or    dx, dx            ; "Any columns left on line?"
  313.     ; Re-enter at bottom of main loop.
  314.     jmp    f_ANSI_exit
  315.  
  316.  
  317. code    ends
  318.     end                ; of nnansi_p.asm
  319.  
  320.